package com.yanx.common.core.domain.manager;

import com.yanx.common.command.receiver.DomainReceiver;
import com.yanx.common.core.domain.entity.IBaseEntity;
import com.yanx.common.core.domain.repository.BaseRepository;
import com.yanx.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

public class BaseManager<E extends IBaseEntity, R extends BaseRepository> implements DomainReceiver {

    protected R repository;

    @Autowired
    public void setRepository(R repository) {
        this.repository = repository;
    }

    // save
    public E save(E entity) {
        return (E) repository.save(entity);
    }

    public List<E> saveAll(Iterable<E> entities) {
        return (List<E>) repository.saveAll(entities);
    }

    //remove
    public <ID extends Serializable> void remove(ID id) {
        repository.deleteById(id);
    }

    public <ID extends Serializable> void remove(Iterable<ID> ids) {
        repository.deleteInBatchById(ids);
    }

    public <ID extends Serializable> void remove(ID[] ids) {
        this.remove(Arrays.asList(ids));
    }

    //update
    public <ID extends Serializable> void update(ID id, Consumer<E> consumer) {
        this.findById(id).ifPresent(t -> {
            consumer.accept(t);
            this.save(t);
        });
    }

    public <ID extends Serializable> void update(ID id, E entity) {
        this.findById(id).ifPresent(t -> this.save(entity));
    }

    public void update(E entity) {
        if (entity.getId() != null) {
            this.update(entity.getId(), entity);
        }
    }

    //invaild
    public <ID extends Serializable> void invaildById(ID id) {
        this.findById(id).ifPresent(entity -> {
            entity.setDeleted(true);
            this.save(entity);
        });
    }

    public <ID extends Serializable> void invaildById(Iterable<ID> ids) {
        Iterable<E> all = this.getAll(ids);
        all.forEach(entity -> {
            entity.setDeleted(true);
        });
        this.saveAll(all);
    }

    public <ID extends Serializable> void invaildById(ID[] ids) {
        this.invaildById(Arrays.asList(ids));
    }

    public void invaild(E entity) {
        entity.setDeleted(true);
        this.save(entity);
    }

    public void invaild(Iterable<E> entitys) {
        entitys.forEach(e -> e.setDeleted(true));
        this.saveAll(entitys);
    }

    public void invaild(E[] entitys) {
        this.invaild(Arrays.asList(entitys));
    }

    //find
    public <ID extends Serializable> Optional<E> findById(ID id) {
        return repository.findById(id);
    }

    public <ID extends Serializable> E getById(ID id) {
        return getById(id, "无记录");
    }

    public <ID extends Serializable> E getById(ID id, CharSequence errorMsg) {
        Optional<E> byId = this.findById(id);
        return byId.filter(u -> !u.getDeleted())
                .orElseThrow(() -> new BusinessException(errorMsg.toString()));
    }

    public List<E> getAll() {
        return repository.findAll();
    }


    public <ID extends Serializable> List<E> getAll(Iterable<ID> ids) {
        Iterable<E> iter = repository.findAll(ids);
        List<E> list = new ArrayList<>();
        iter.forEach(list::add);
        return list;
    }

}
